/*-------------------------------------------------------------------
 *	Copyright (c) 2013 Zhirnov Andrey
 *	All rights reserved.
 *-----------------------------------------------------------------*/
/*
	This library based on code from "libnoise" project by Jason Bevins.
	See "libnoise" licence in "COPYING.txt"
*/

/*
-------------------------------------------------------------------------------
*	The GNU Lesser General Public License
*
*	This program is free software: you can redistribute it and/or modify
*	it under the terms of the GNU Lesser General Public License as published by
*	the Free Software Foundation, either version 3 of the License, or
*	(at your option) any later version.
*
*	This program is distributed in the hope that it will be useful,
*	but WITHOUT ANY WARRANTY; without even the implied warranty of
*	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*	GNU Lesser General Public License for more details.
*
*	You should have received a copy of the GNU Lesser General Public License
*	along with this program. If not, see http://www.gnu.org/licenses/.
-------------------------------------------------------------------------------
*/


#ifndef __LIB_NOISE_CL_H_
#define __LIB_NOISE_CL_H_

/*
 *	User options:
 *	#define NOISE_STATIC		- attach as static library
 *	#define NOISE_NO_PROTOTYPES - disable function prototypes
 *
 *	Developer options:
 *	#define _NOISE_BUILD		- to compile library
 *
 *	Helpers:
 *	#define NOISE_CODE_GEN( _buildFunction ) - macros for code generation
 */


namespace Noise
{

#ifdef _MSC_VER
#	define _NOISE_DLL_EXPORT	__declspec(dllexport)
#	define _NOISE_DLL_IMPORT	__declspec(dllimport)
#	define NOISE_CALL			__stdcall
#endif


#ifdef __GNUC__
# if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || \
	 defined(WIN64) || defined(__CYGWIN__) || defined(__MINGW32__)
// Windows platform
#	define _NOISE_DLL_EXPORT	__attribute__ (dllexport)
#	define _NOISE_DLL_IMPORT	__attribute__ (dllimport)
#	define NOISE_CALL			__stdcall
# else
// Posix platform
#	define _NOISE_DLL_EXPORT	__attribute__ (visibility("default"))
#	define _NOISE_DLL_IMPORT	__attribute__ (visibility("default"))
#	define NOISE_CALL
# endif
#endif


#ifdef NOISE_STATIC
#	define NOISE_ENTRY	extern
#else
# ifdef _NOISE_BUILD
#	define NOISE_ENTRY	extern _NOISE_DLL_EXPORT
# else
#	define NOISE_ENTRY	extern _NOISE_DLL_IMPORT
# endif
#endif


	/*
	 * Result Code
	 */
	enum EResult
	{
		/*
		 * No errors.
		 */
		OK					= 0,

		/*
		 * One or more of input values are invalid.
		 */
		INVALID_VALUE		= -1,

		/*
		 * One or more of input enumeration constant values are not supported.
		 */
		INVALID_ENUM		= -2,

		/*
		 * Invalid function source object.
		 */
		INVALID_SOURCE		= -3,

		/*
		 * Invalid program object.
		 */
		INVALID_PROGRAM		= -4,

		/*
		 * Invalid operation, some thing wrong in context.
		 */
		INVALID_OPERATION	= -5,

		/*
		 * No implementation (development only).
		 */
		_NO_IMPLEMENTATION	= -100,
	};


	typedef struct _Source {} *		Source;
	typedef struct _Program {} *	Program;
	typedef struct _Context {} *	Context;


/* OpenGL Types */
#if !defined(__gl_h_)
	typedef int				GLenum;
	typedef unsigned int	GLuint;
#endif

/* OpenCL Types */
#if !defined(__OPENCL_H)
	typedef struct _cl_mem *			cl_mem;
	typedef struct _cl_platform_id *	cl_platform_id;
	typedef struct _cl_device_id *		cl_device_id;
	typedef struct _cl_context *		cl_context;
#endif

/* DirectX10 Types */
#if !defined(__d3d11_h__) && !defined(__d3d10_h__)
	typedef struct _ID3D10Device *		ID3D10Device;
	typedef struct _ID3D10Buffer *		ID3D10Buffer;
	typedef struct _ID3D10Texture2D *	ID3D10Texture2D;
	typedef struct _ID3D10Texture3D *	ID3D10Texture3D;
#endif

#ifdef __cplusplus
	extern "C" {
#endif



/*============================================================================*/
/* FUNCTION SOURCE OBJECT */
		

	/*
	 * Function Source Type
	 */
	enum ESource
	{
		/*					[num sources] description									*/

		NONE = 0,		/* used for ESourceQuery::SOURCE_TYPE only						*/

		/* math */
		ABS,			/* [1]	abs( src0 )												*/
		ADD,			/* [2]	src0 + src1												*/
		CLAMP,			/* [3]	clamp( src0, src1, src2 )								*/
		CONSTANT,		/* [0]	value													*/
		DIV,			/* [2]	src0 / src1												*/
		INV,			/* [1]	-src0													*/
		MAD,			/* [3]	mad( src0, src1, src2 ) == src0 * src1 + src2			*/
		MAX,			/* [2]	max( src0, src1 )										*/
		MIN,			/* [2]	min( src0, src1 )										*/
		MIX,			/* [3]	mix( src0, src1, src2 )									*/
		MOD,			/* [2]	src0 % src1												*/
		MUL,			/* [2]	src0 * src1												*/
		NORM_EXP,		/* [2]	pow( abs((src0 + 1) / 2), src1 ) * 2 - 1				*/
		EXP,			/* [1]	exp( src0 )												*/
		EXP2,			/* [1]	exp2( src0 )											*/
		EXP10,			/* [1]	exp10( src0 )											*/
		LOG,			/* [1]	log( src0 )												*/
		LOG2,			/* [1]	log2( src0 )											*/
		LOG10,			/* [1]	log10( src0 )											*/
		POW,			/* [2]	pow( src0, src1 )										*/
		SCALE_BIAS,		/* [1]	src0 * scale + bias										*/
		SUB,			/* [1]	src0 - src1												*/

		/* transform coordinate */
		DISPLACE,		/* [4]	src0[ pos + (src1, src2, src3) ]						*/
		SCALE_POINT,	/* [1]	src0[ pos * scale ]										*/
		TRANSLATE_POINT,/* [1]	src0[ pos + translate ]									*/
		ROTATE_POINT,	/* [1]	src0[ pos * rotateMat3 ]								*/

		/* noise generators */
		BILLOW,			/* [0]	billowy noise											*/
		CHECKERBOARD,	/* [0]	checkerboard pattern									*/
		CURVE,			/* [1]	map source to function curve							*/
		CYLINDERS,		/* [0]	generate cylinders										*/
		PERLIN,			/* [0]	perlin noise											*/
		RIDGED_MULTI,	/* [0]	ridged-multifractal noise								*/
		SELECT,			/* [3]	(src0, src1)[src2]										*/
		SPHERES,		/* [0]	generate spheres										*/
		TERRACE,		/* [1]	map source to terrace-forming curve						*/
		TURBULENCE,		/* [1]	randomly displaces source								*/
		VORONOI,		/* [0]	Voronoi cells											*/

		/* control */
		//CACHE,			/* [1..4]	save to image and sync threads					*/
		RENDER_OUTPUT,	/* [1..4]	output = (src0, src1, src2, src3)					*/
		GRADIENT,		/* [1]		output = mix(colors[src0], colors[src0+1])			*/
		SWIZZLE,		/* [1]		output = output.swizzle( r, g, b, a )				*/
	};

	/*
	 * Function Argument Type
	 */
	enum EArgument
	{
		SOURCE_0 = 1,			/* Source */
		SOURCE_1,				/* Source */
		SOURCE_2,				/* Source */
		SOURCE_3,				/* Source */
		SOURCE_4,				/* Source */
		SOURCE_5,				/* Source */
		SOURCE_6,				/* Source */
		SOURCE_7,				/* Source */

		/* SCALE_BIAS: */
		ARG_SCALE,				/* float */
		ARG_BIAS,				/* float */

		/* CONSTANT: */
		ARG_CONST,				/* float */

		/* BILLOW, PERLIN: */
		ARG_PERSISTENCE,		/* float */
		ARG_LACUNARITY,			/* float */
		ARG_FREQUENCY,			/* float */
		ARG_OCTAVE_COUNT,		/* int */
		ARG_NOISE_QUALITY,		/* ENoiseQuality */
		ARG_SEED,				/* int */

		/* RIDGED_MULTI: */
		/* reuse ARG_LACUNARITY	   (float) */
		/* reuse ARG_FREQUENCY	   (float) */
		/* reuse ARG_OCTAVE_COUNT  (int) */
		/* reuse ARG_NOISE_QUALITY (ENoiseQuality) */
		/* reuse ARG_SEED		   (int) */

		/* CURVE: */
		ARG_ADD_CONTROL_POINTS,	/* float[2] (for SetArg* only) */
		ARG_CONTROL_POINTS,		/* float[2][] can be empty for clear array */

		/* CYLINDERS: */
		/* reuse ARG_FREQUENCY	  (float) */

		/* SELECT: */
		ARG_EDGE_FALLOFF,		/* float */
		ARG_LOWER_BOUND,		/* float */
		ARG_UPPER_BOUND,		/* float */

		/* TURBULENCE: */
		/* reuse ARG_FREQUENCY	  (float) */
		/* reuse ARG_SEED		  (int) */
		ARG_POWER,				/* float */
		ARG_ROUGHNESS,			/* float */

		/* VORONOI: */
		/* reuse ARG_FREQUENCY	  (float) */
		/* reuse ARG_SEED		  (int) */
		ARG_DISPLACEMENT,		/* float */
		ARG_ENABLE_DISTANCE,	/* int */

		/* SCALE_POINT: */
		ARG_SCALE_XYZ,			/* float[3] */

		/* TRANSLATE_POINT: */
		ARG_TRANSLATE,			/* float[3] */

		/* ROTATE_POINT: */
		ARG_ROTATION_MAT3,		/* float[3*3] column major */

		/* TERRACE: */
		ARG_INVERT_TERRACES,	/* int (bool) */

		/* GRADIENT: */
		ARG_ADD_COLOR_POINTS,	/* float[4][] - (point, color[3]) */
		ARG_COLOR_POINTS,		/* float[4][] */

		/* SWIZZLE: */
		ARG_SWIZZLE,
	};

	/*
	 * Noise Quality flags
	 */
	enum ENoiseQuality
	{
		QUALITY_FAST	= 0,
		QUALITY_STD		= 1,
		QUALITY_BEST	= 2
	};

	/*
	 * Function Source State
	 */
	enum ESourceState
	{
		SOURCE_COMPLETE = 0,
		UNCOMPLETE_ATTACHMENT_SOURCE,
		UNCOMPLETE_DATA,
	};

	/*
	 * Function Source Query Type
	 */
	enum ESourceQuery
	{
		SOURCE_STATE = 1,		/* ESourceState */
		SOURCE_TYPE,			/* ESource */
		SOURCES_COUNT,			/* int - count of all attached functions */
		INPUT_SOURCES,			/* int */

		/* BILLOW, PERLIN */
		MAX_OCTAVES,			/* int */

		/* CURVE, TERRACE */
		CONTROL_POINTS_COUNT,	/* int */
	};


	/*
	 * Source function types.
	 */
	typedef Source (NOISE_CALL * PFNnCreateSourcePROC) (ESource type);
	typedef Source (NOISE_CALL * PFNnCreateSourceCopyPROC) (Source src);
	typedef void (NOISE_CALL * PFNnDeleteSourcePROC) (Source src);
	typedef EResult (NOISE_CALL * PFNnGetSourceIntegerPROC) (Source src, ESourceQuery pname, int *v, int count);
	typedef EResult (NOISE_CALL * PFNnSetArgSourcePROC) (Source src, EArgument type, Source inputSource);
	typedef EResult (NOISE_CALL * PFNnSetArgDoublePROC) (Source src, EArgument type, const double *v, int count);
	typedef EResult (NOISE_CALL * PFNnSetArgFloatPROC) (Source src, EArgument type, const float *v, int count);
	typedef EResult (NOISE_CALL * PFNnSetArgIntegerPROC) (Source src, EArgument type, const int *v, int count);
	typedef EResult (NOISE_CALL * PFNnGetArgSourcePROC) (Source src, EArgument type, Source *inputSource);
	typedef EResult (NOISE_CALL * PFNnGetArgDoublePROC) (Source src, EArgument type, double *v, int count);
	typedef EResult (NOISE_CALL * PFNnGetArgFloatPROC) (Source src, EArgument type, float *v, int count);
	typedef EResult (NOISE_CALL * PFNnGetArgIntegerPROC) (Source src, EArgument type, int *v, int count);


#if !defined(NOISE_NO_PROTOTYPES)

	/*
	 * nCreateSource - create function source object.
	 *
	 * return:
	 *	- Zero if function source type is not supported.
	 *	- Valid function source object otherwise.
	 */
	NOISE_ENTRY Source NOISE_CALL nCreateSource (ESource type);

	/*
	 * nCreateSourceCopy - create copy of function source. Attachment sources not copied.
	 *
	 * return:
	 *	- Zero if function source type is not supported.
	 *	- Valid function source object otherwise.
	 */
	NOISE_ENTRY Source NOISE_CALL nCreateSourceCopy (Source src);

	/*
	 * nDeleteSource - delete function source.
	 */
	NOISE_ENTRY void NOISE_CALL nDeleteSource (Source src);
	
	/*
	 * nGetSourceInteger - get parameter from function source.
	 *
	 * errors:
	 *	INVALID_VALUE	- if 'count' less then required size of vector.
	 *	INVALID_ENUM	- if 'type' is not supported for this function source.
	 *	INVALID_SOURCE	- if 'src' is Null.
	 */
	NOISE_ENTRY EResult NOISE_CALL nGetSourceInteger (Source src, ESourceQuery pname, int *v, int count);

	/*
	 * nSetArg* - set arguments to function source.
	 *
	 * errors:
	 *	INVALID_VALUE	- if 'count' less then required size of vector.
	 *	INVALID_ENUM	- if 'type' is not supported for this function source.
	 *	INVALID_SOURCE	- if 'src' is Null.
	 *	INVALID_SOURCE	- for 'nSetArgSource' - if can't attach 'src' to 'src'.
	 */
	NOISE_ENTRY EResult NOISE_CALL nSetArgSource (Source src, EArgument type, Source inputSource);
	NOISE_ENTRY EResult NOISE_CALL nSetArgDouble (Source src, EArgument type, const double *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nSetArgFloat (Source src, EArgument type, const float *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nSetArgInteger (Source src, EArgument type, const int *v, int count);
	
	/*
	 * nGetArg* - get arguments from function source.
	 *
	 * errors:
	 *	INVALID_VALUE	- if 'count' less then required size of vector.
	 *	INVALID_ENUM	- if 'type' is not supported for this function source.
	 *	INVALID_SOURCE	- if 'src' is Null.
	 */
	NOISE_ENTRY EResult NOISE_CALL nGetArgSource (Source src, EArgument type, Source *inputSource);
	NOISE_ENTRY EResult NOISE_CALL nGetArgDouble (Source src, EArgument type, double *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nGetArgFloat (Source src, EArgument type, float *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nGetArgInteger (Source src, EArgument type, int *v, int count);

#endif	/* NOISE_NO_PROTOTYPES */

	
/*============================================================================*/
/* NOISE PROGRAM OBJECT */
	

	/*
	 * Program Type
	 */
	enum EProgram
	{
		OPENCL_PROGRAM = 1,		/* supported in version 1.0 */
		NATIVE_PROGRAM,			/* supported in version 1.0 */
		OPENGL_PROGRAM,			/* whil be supported later */
		OPENGL_COMPUTE_PROGRAM,	/* whil be supported later */
		DIRECTX_PROGRAM,		/* whil be supported later */
		DIRECTX_COMPUTE_PROGRAM,/* whil be supported later */
		CG_PROGRAM,				/* whil be supported later */
	};

	/*
	 * Program Query Type
	 */
	enum EProgramQuery
	{
		PROGRAM_BUILD_STATE = 1,	/* int - TRUE or FALSE */
		PROGRAM_TYPE,				/* int - EProgram */
		PROGRAM_OUT_FORMAT,			/* int - EPixelFormat */
		PROGRAM_BUILD_LOG_LENGTH,	/* int */
		PROGRAM_BUILD_LOG,			/* string - log of building program from source */
		PROGRAM_COMPILE_LOG_LENGTH,	/* int */
		PROGRAM_COMPILE_LOG,		/* string - log of OpenCL program compilation log */
		PROGRAM_SOURCE_LENGTH,		/* int */
		PROGRAM_SOURCE,				/* string - OpenCL program source */
		PROGRAM_BINARY_LENGTH,		/* int */
		PROGRAM_BINARY,				/* string (byte[]) - OpenCL binary program */
		PROGRAM_CL_POINTER,			/* int or int[2] (cl_program) */
		PROGRAM_BUILD_OPTIONS,		/* int (EBuildOptions) */
		PROGRAM_MAX_IMAGE_SIZE,		/* int[1..3] - return maximum size of image */
		PROGRAM_NUM_IMAGE_FORMATS,	/* int - number of supported pixel formats */
		PROGRAM_IMAGE_FORMATS,		/* int[2][] (EPixelFormat, EPixelType) */
		PROGRAM_SHOW_IMAGE_PREVIEW,	/* int (bool) */
		PROGRAM_COORD_BOUNDS,		/* float[6] - bounds for 3-axises */
	};

	/*
	 * Program Parameter
	 */
	enum EProgramParameter
	{
		COORD_BOUNDS = 1,			/* float[6] - coordinate bounds for 3-axises */
		SHOW_IMAGE_PREVIEW,			/* int (bool) - show image in image viewer after rendering */
	};

	/*
	 * Program Build Options
	 */
	enum EBuildOptions
	{
		BUILD_FLOAT16				= 1 << 0,	/* use half floating point values */
		BUILD_FLOAT32				= 1 << 1,	/* use single floating point values */
		BUILD_FLOAT64				= 1 << 2,	/* use double floating point values */

		BUILD_OUTPUT_IMAGE_2D		= 1 << 3,	/* write result to 2D image */
		BUILD_OUTPUT_IMAGE_3D		= 1 << 4,	/* write result to 3D image (it may be unsupported) */

		BUILD_OUTPUT_FLOAT			= 1 << 5,	/* write result to image with float or normalized pixel format */
		BUILD_OUTPUT_SIGNED_INT		= 1 << 6,	/* write result to image with signed integer pixel format */
		BUILD_OUTPUT_UNSIGNED_INT	= 1 << 7,	/* write result to image with unsigned integer pixel format */

		DEFAULT_OPTIONS				= BUILD_FLOAT32 | BUILD_OUTPUT_IMAGE_2D | BUILD_OUTPUT_FLOAT,
	};

	/*
	 * Texture Pixel Format Type
	 */
	enum EPixelFormat
	{
		R = 1,
		RG,
		RGB,
		RGBA,
	};

	/*
	 * Texture Pixel Type
	 */
	enum EPixelType
	{
		SINT8 = 1,
		SINT16,
		SINT32,
		UINT8,
		UINT16,
		UINT32,
		FLOAT16,
		FLOAT32,
		//FLOAT64_UINT32X2,	/* save float64 as uint32 x2, format must be R or RG */
		FLOAT64,			/* if supported double floating point value */
		SNORM_8,
		SNORM_16,
		UNORM_8,
		UNORM_16,
		UNORM_5_6_5,		/* format must be RGB */
		UNORM_10_10_10,		/* format must be RGB */
	};

	/*
	 * Image Type
	 */
	enum EImageType
	{
		BMP = 1,
		BMP_PACKED_FLOAT24,		/* pack float to RGB8 color */
		CUSTOM_FLOAT,			/* header: int dim[3], int channels, int sizeOfFloat; */
	};

	/*
	 * Image Unpack helpers.
	 */
	#define NOISE_UNPACK_FLOAT24( /*in*/_bgr ) \
	 	((float(_bgr[2]) / 255.0f) + \
		 (float(_bgr[1]) / 65025.0f) + \
		 (float(_bgr[0]) / 16581375.0f))
	
	#define NOISE_CUSTOM_FLOAT_HEADER_SIZE	sizeof(int)*6
	#define NOISE_CUSTOM_FLOAT_PARSE_HEADER( /*in*/_header, /*out*/_width, _height, _depth, _channels, _sizeOfFloat, _dataSize ) {\
		_width = _header[0]; \
		_height = _header[1]; \
		_depth = _header[2]; \
		_channels = _header[3]; \
		_sizeOfFloat = _header[4]; \
		_dataSize = (_width * _height * _depth * _channels * _sizeOfFloat); \
	}


	/*
	 * Program function types.
	 */
	typedef Program (NOISE_CALL * PFNnCreateProgramPROC) (EProgram type);
	typedef void (NOISE_CALL * PFNnDeleteProgramPROC) (Program prog);
	typedef EResult (NOISE_CALL * PFNnBuildProgramPROC) (Program prog, Source src, EBuildOptions options);
	typedef EResult (NOISE_CALL * PFNnGetProgramIntegerPROC) (Program prog, EProgramQuery pname, int *v, int count);
	typedef EResult (NOISE_CALL * PFNnGetProgramFloatPROC) (Program prog, EProgramQuery pname, float *v, int count);
	typedef EResult (NOISE_CALL * PFNnGetProgramDoublePROC) (Program prog, EProgramQuery pname, double *v, int count);
	typedef EResult (NOISE_CALL * PFNnGetProgramStringPROC) (Program prog, EProgramQuery pname, char *buf, int length);
	typedef EResult (NOISE_CALL * PFNnRenderToMemoryPROC) (Program prog, int width, int height, int depth, int rowSize, int sliceSize, EPixelFormat format, EPixelType type, void *pixels);
	typedef EResult (NOISE_CALL * PFNnRenderToImagePROC) (Program prog, int width, int height, int depth, EPixelFormat format, EPixelType type, EImageType imageType, const char *filename);
	typedef EResult (NOISE_CALL * PFNnRenderToImageCLPROC) (Program prog, cl_mem imageId);
	typedef EResult (NOISE_CALL * PFNnRenderToTextureGLPROC) (Program prog, GLenum target, GLuint texId, int level);
	typedef EResult (NOISE_CALL * PFNnRenderToTextureDXPROC) (Program prog, void *dxTex);



#if !defined(NOISE_NO_PROTOTYPES)

	/*
	 * nCreateProgram - create program object.
	 *
	 * return:
	 *	- Zero if program type is not supported.
	 *	- Valid program object otherwise.
	 */
	NOISE_ENTRY Program NOISE_CALL nCreateProgram (EProgram type);

	/*
	 * nDeleteProgram - delete program object.
	 */
	NOISE_ENTRY void NOISE_CALL nDeleteProgram (Program prog);

	/*
	 * nBuildProgram - build program from functions source object.
	 *
	 * errors:
	 *	INVALID_SOURCE	- if 'src' is Null.
	 *	INVALID_SOURCE	- if 'src' is not complete, call nGetSourceInteger with parameter SOURCE_STATE to check.
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 *	INVALID_OPERATION - if can't build program with this source.
	 */
	NOISE_ENTRY EResult NOISE_CALL nBuildProgram (Program prog, Source src, EBuildOptions options);

	/*
	 * nSetProgram* - set integer/float/double parameter to program object.
	 *
	 * errors:
	 *	INVALID_VALUE	- if 'count' less than size of vector.
	 *	INVALID_ENUM	- if 'type' is not supported for this program or with this arg type.
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 */
	NOISE_ENTRY EResult NOISE_CALL nSetProgramInteger (Program prog, EProgramParameter pname, const int *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nSetProgramFloat (Program prog, EProgramParameter pname, const float *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nSetProgramDouble (Program prog, EProgramParameter pname, const double *v, int count);

	/*
	 * nGetProgram* - get integer/float/double parameter form program object.
	 *
	 * errors:
	 *	INVALID_VALUE	- if 'count' less then required size of vector.
	 *	INVALID_ENUM	- if 'type' is not supported for this program or with this arg type (int/float/double).
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 */
	NOISE_ENTRY EResult NOISE_CALL nGetProgramInteger (Program prog, EProgramQuery pname, int *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nGetProgramFloat (Program prog, EProgramQuery pname, float *v, int count);
	NOISE_ENTRY EResult NOISE_CALL nGetProgramDouble (Program prog, EProgramQuery pname, double *v, int count);

	/*
	 * nGetProgramString - get string parameter form program object.
	 *
	 * erros:
	 *	INVALID_VALUE	- if 'length' less then required size of string.
	 *	INVALID_ENUM	- if 'type' is not supported for this program.
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 */
	NOISE_ENTRY EResult NOISE_CALL nGetProgramString (Program prog, EProgramQuery pname, char *buf, int length);

	/*
	 * nRenderToMemory - render noise to memory.
	 *
	 * erros:
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 *	INVALID_PROGRAM	- if 'prog' is not builded, call nGetProgramInteger with parameter PROGRAM_BUILD_STATE to check.
	 *	INVALID_VALUE	- if 'width', 'height' or 'depth' is invalid, check: 0 <= x < PROGRAM_MAX_IMAGE_SIZE.
	 *	INVALID_VALUE	- if 'pixels' is Null.
	 *	INVALID_ENUM	- if 'format' or 'type' is not supported.
	 *	INVALID_OPERATION- on internal error.
	 */
	NOISE_ENTRY EResult NOISE_CALL nRenderToMemory (Program prog,
													int width,
													int height,
													int depth,
													int rowSize,
													int sliceSize,
													EPixelFormat format,
													EPixelType type,
													void *pixels);

	/*
	 * nRenderToImage - render noise to image and save to file.
	 *
	 * errors:
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 *	INVALID_PROGRAM	- if 'prog' is not builded, call nGetProgramInteger with parameter PROGRAM_BUILD_STATE to check.
	 *	INVALID_VALUE	- if 'width', 'height' or 'depth' is invalid, check: 0 <= x < PROGRAM_MAX_IMAGE_SIZE.
	 *	INVALID_VALUE	- if 'filename' is Null or not valid image file name (without extension, etc).
	 *	INVALID_ENUM	- if 'format' or 'type' is not supported.
	 *	INVALID_VALUE	- if 'imageType' is not supported.
	 *	INVALID_OPERATION- on internal error.
	 */
	NOISE_ENTRY EResult NOISE_CALL nRenderToImage (Program prog,
												   int width,
												   int height,
												   int depth,
												   EPixelFormat format,
												   EPixelType type,
												   EImageType imageType,
												   const char *filename);

	/*
	 * nRenderToImage - render noise to OpenCL image.
	 *
	 * errors:
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 *	INVALID_PROGRAM	- if 'prog' is not builded, call nGetProgramInteger with parameter PROGRAM_BUILD_STATE to check.
	 *	INVALID_VALUE	- if 'id' is not OpenCL image or not valid to render.
	 *	INVALID_OPERATION- on internal error.
	 */
	NOISE_ENTRY EResult NOISE_CALL nRenderToImageCL (Program prog, cl_mem imageId);
	
	NOISE_ENTRY EResult NOISE_CALL nRenderToSubImageCL (Program prog,
														cl_mem imageId,
														int xoffset,
														int yoffset,
														int zoffset,
														int width,
														int height,
														int depth);

	/*
	 * nRenderToTextureGL - render noise to OpenGL texture.
	 *
	 * erros:
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 *	INVALID_PROGRAM	- if 'prog' is not builded, call nGetProgramInteger with parameter PROGRAM_BUILD_STATE to check.
	 *	INVALID_VALUE	- if 'target' or 'texId' is invalid (can't create OpenCL texture).
	 *	INVALID_OPERATION- if no shared OpenGL context.
	 *	INVALID_OPERATION- on internal error.
	 */
	NOISE_ENTRY EResult NOISE_CALL nRenderToTextureGL (Program prog, GLenum target, GLuint texId, int level);
	/*
	NOISE_ENTRY EResult NOISE_CALL nRenderToSubTextureGL  (	Program prog,
															GLenum target,
															GLuint texId,
															int level,
															int xoffset,
															int yoffset,
															int zoffset,
															int width,
															int height,
															int depth,
															EPixelFormat format,
															EPixelType type);*/

	/*
	 * nRenderToBufferGL - render noise to OpenGL vertex buffer as 3D image.
	 *//*
	NOISE_ENTRY EResult NOISE_CALL nRenderToBufferGL (Program prog,
													  GLuint bufId,
													  int width,
													  int height,
													  int depth,
													  int rowSize,
													  int sliceSize,
													  EPixelFormat format,
													  EPixelType type);*/

	/*
	 * nRenderToTextureDX - render noise to DirectX texture.
	 *
	 * erros:
	 *	INVALID_PROGRAM	- if 'prog' is Null.
	 *	INVALID_PROGRAM	- if 'prog' is not builded, call nGetProgramInteger with parameter PROGRAM_BUILD_STATE to check.
	 *	INVALID_VALUE	- if 'target' or 'id' is invalid (can't create OpenCL texture).
	 *	INVALID_OPERATION- if no shared DirectX context.
	 *	INVALID_OPERATION- on internal error.
	 */
	NOISE_ENTRY EResult NOISE_CALL nRenderToTextureDX (Program prog, void *dxTex);
	
	/*
	 * nRenderToBufferDX - render noise to DirectX vertex buffer as 3D image.
	 *//*
	NOISE_ENTRY EResult NOISE_CALL nRenderToBufferDX (Program prog,
													  void *buf,
													  int width,
													  int height,
													  int depth,
													  int rowSize,
													  int sliceSize,
													  EPixelFormat format,
													  EPixelType type);*/

#endif	/* NOISE_NO_PROTOTYPES */

	


/*============================================================================*/
/* CONTEXT */


	/*
	 * Context Query Type
	 */
	enum EContextQuery
	{
		CONTEXT_VERSION = 1,				/* return version of libNoiseCL */
		CONTEXT_CREATED,					/* int (bool) */
		CONTEXT_FLOAT_POINT_TYPE_SIZE,		/* return sizeof(real), can be 16, 32 or 64 */
		CONTEXT_SHARED_WITH_GL,				/* int (bool) */
		CONTEXT_SHARED_WITH_DX,				/* int (bool) */
		CONTEXT_SUPPORTED_SOURCES_COUNT,	/* int - number of supported source objects */
		CONTEXT_SUPPORTED_SOURCES,			/* int[] (ESource) */
		CONTEXT_SUPPORTED_PROGRAMS_COUNT,	/* int - number of supported program objects */
		CONTEXT_SUPPORTED_PROGRAMS,			/* int[] (EProgram) */
		CONTEXT_IMAGE_VIEWER_SIZES,			/* int[2] */
	};

	/*
	 * Context Parameter Type
	 */
	enum EContextParameter
	{
		IMAGE_VIEWER_SIZES = 1,		/* int[2] - width and height of window in pixels*/
		IMAGE_VIEWER_FLAGS,			/* int (EImageViewerFlags) */
		//IMAGE_VIEWER_LAYER,		/* int - layer of 3D image */
	};

	/*
	 * Image Viewer Flags
	 */
	enum EImageViewerFlags
	{
		RENDER_MONO_TEXTURE			= 1 << 0,	/* draw gray scale texture */
		RENDER_COLOR_TEXTURE		= 1 << 1,	/* simple draw texture */
		RENDER_TEXTURE_PER_CHANNEL	= 1 << 2,	/* draw 4 quads with one of texture channel */
	};

	/*
	 * Context Initialization Flags
	 */
	enum EContextFlags
	{
		//CL_DEVICE_GPU			= 1 << 0,	/* use OpenCL GPU device with high perfomance */
		//CL_DEVICE_GPU_SECONDARY	= 1 << 1,	/* use OpenCL GPU device with perfomance lesser than high */
		//CL_DEVICE_CPU			= 1 << 2,	/* use OpenCL CPU device with high perfomance */
		SUPPORT_IMAGE_VIEWER	= 1 << 3,
		CONTEXT_DEFAULT_FLAGS	= SUPPORT_IMAGE_VIEWER,
	};
	

	/*
	 * Context function types.
	 */
	typedef EResult (NOISE_CALL * PFNnCreateContextPROC) (EContextFlags flags);
	typedef EResult (NOISE_CALL * PFNnCreateContextFromCLPROC) (cl_platform_id platformId, cl_device_id deviceId, cl_context context);
	typedef EResult (NOISE_CALL * PFNnCreateContextFromGLPROC) (void *dc, void *rc, EContextFlags flags);
	typedef EResult (NOISE_CALL * PFNnCreateContextFromDXPROC) (void *dxDevice, EContextFlags flags);
	typedef void (NOISE_CALL * PFNnDeleteContextPROC) ();
	typedef EResult (NOISE_CALL * PFNnGetContextIntegerPROC) (EContextQuery pname, int *v, int count);



#if !defined(NOISE_NO_PROTOTYPES)

	/*
	 * nCreateContext - create libNoiseCL context.
	 *
	 * errors:
	 *	INVALID_OPERATION - if can't create linNoiseCL context.
	 */
	NOISE_ENTRY EResult NOISE_CALL nCreateContext (EContextFlags flags);

	/*
	 * nCreateContextFromCL - create libNoiseCL context form user's OpenCL context.
	 *
	 * errors:
	 *	INVALID_VALUE	  - if 'platformID', 'deviceId' or 'context' is invalid.
	 *	INVALID_OPERATION - if can't create libNoiseCL context.
	 */
	NOISE_ENTRY EResult NOISE_CALL nCreateContextFromCL (cl_platform_id platformId, cl_device_id deviceId, cl_context context);

	/*
	 * nShareContextGL - create libNoiseCL context and share with user's OpenGL context.
	 *
	 * errors:
	 *	INVALID_VALUE	  - if 'dc' or 'rc' is invalid.
	 *	INVALID_OPERATION - if can't create linNoiseCL context.
	 *	INVALID_OPERATION - if can't share contexts.
	 */
	NOISE_ENTRY EResult NOISE_CALL nCreateContextFromGL (void *dc, void *rc, EContextFlags flags);

	/*
	 * nShareContextDX - create libNoiseCL context and share with user's DirectX context.
	 *
	 * errors:
	 *	INVALID_VALUE	  - if 'dxDevice' is invalid.
	 *	INVALID_OPERATION - if can't create linNoiseCL context.
	 *	INVALID_OPERATION - if can't share contexts.
	 */
	NOISE_ENTRY EResult NOISE_CALL nCreateContextFromDX (void *dxDevice);

	/*
	 * nDeleteContext - delete linNoiseCL context.
	 */
	NOISE_ENTRY void NOISE_CALL nDeleteContext ();

	/*
	 * nSetContextInteger - set integer parameter to context.
	 *
	 * errors:
	 *	INVALID_ENUM	- if 'pname' is not suported.
	 *	INVALID_VALUE	- if 'count' is less than size of vector.
	 */
	NOISE_ENTRY EResult NOISE_CALL nSetContextInteger (EContextParameter pname, const int *v, int count);

	/*
	 * nGetContextInteger - get integer parameter from context.
	 *
	 * errors:
	 *	INVALID_ENUM	- if 'pname' is not supported.
	 *	INVALID_VALUE	- if 'count' is less than size of required vector.
	 */
	NOISE_ENTRY EResult NOISE_CALL nGetContextInteger (EContextQuery pname, int *v, int count);

#endif	/* NOISE_NO_PROTOTYPES */
	

/*============================================================================*/


#ifdef __cplusplus
	}	/* extern "C" */
#endif


/* Code Generation */
#define NOISE_BUILD_FUNCTION( _returnType, _functionName, _arguments, _defaultReturnValue ) \
	NOISE_ENTRY _returnType NOISE_CALL _functionName _arguments;

#define NOISE_CODE_GEN( buildFunction ) \
	/* Source */ \
	buildFunction( Source,  nCreateSource, (ESource type), null ); \
	buildFunction( Source,  nCreateSourceCopy, (Source src), null ); \
	buildFunction( void,    nDeleteSource, (Source src), ); \
	buildFunction( EResult, nGetSourceInteger, (Source src, ESourceQuery pname, int *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nSetArgSource, (Source src, EArgument type, Source inputSource), INVALID_OPERATION ); \
	buildFunction( EResult, nSetArgDouble, (Source src, EArgument type, const double *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nSetArgFloat, (Source src, EArgument type, const float *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nSetArgInteger, (Source src, EArgument type, const int *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nGetArgSource, (Source src, EArgument type, Source *src), INVALID_OPERATION ); \
	buildFunction( EResult, nGetArgDouble, (Source src, EArgument type, double *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nGetArgFloat, (Source src, EArgument type, float *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nGetArgInteger, (Source src, EArgument type, int *v, int count), INVALID_OPERATION ); \
	/* Program */ \
	buildFunction( Program, nCreateProgram, (EProgram type), INVALID_OPERATION ); \
	buildFunction( void,    nDeleteProgram, (Program prog), INVALID_OPERATION ); \
	buildFunction( EResult, nBuildProgram, (Program prog, Source src, EBuildOptions options), INVALID_OPERATION ); \
	buildFunction( EResult, nGetProgramInteger, (Program prog, EProgramQuery pname, int *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nGetProgramFloat, (Program prog, EProgramQuery pname, float *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nGetProgramDouble, (Program prog, EProgramQuery pname, double *v, int count), INVALID_OPERATION ); \
	buildFunction( EResult, nGetProgramString, (Program prog, EProgramQuery pname, char *buf, int length), INVALID_OPERATION ); \
	buildFunction( EResult, nRenderToMemory, (Program prog, int width, int height, int depth, int rowSize, int sliceSize, EPixelFormat format, EPixelType type, void *pixels), INVALID_OPERATION ); \
	buildFunction( EResult, nRenderToImage, (Program prog, int width, int height, int depth, EPixelFormat format, EPixelType type, EImageType imageType, const char *filename), INVALID_OPERATION ); \
	buildFunction( EResult, nRenderToImageCL, (Program prog, cl_mem imageId), INVALID_OPERATION ); \
	buildFunction( EResult, nRenderToTextureGL, (Program prog, GLenum target, GLuint texId), INVALID_OPERATION ); \
	buildFunction( EResult, nRenderToTextureDX, (Program prog, void *dxTex), INVALID_OPERATION ); \
	/* Context */ \
	buildFunction( EResult, nCreateContext, (EContextFlags flags), INVALID_OPERATION ); \
	buildFunction( EResult, nCreateContextFromCL, (cl_platform_id platformId, cl_device_id deviceId, cl_context context), INVALID_OPERATION ); \
	buildFunction( EResult, nCreateContextFromGL, (void *dc, void *rc, EContextFlags flags), INVALID_OPERATION ); \
	/*buildFunction( EResult, nCreateContextFromDX, (void *dxDevice, EContextFlags flags), INVALID_OPERATION );*/ \
	buildFunction( void,    nDeleteContext, (), ); \
	buildFunction( EResult, nGetContextInteger, (EContextQuery pname, int *v, int count), INVALID_OPERATION ); \
	

}	/* Noise */

#endif	/* __LIB_NOISE_CL_H_ */